package org.tinygroup.dbcluster.sample.algorithm;

import com.google.common.collect.Range;
import org.tinygroup.dbcluster.algorithm.database.SingleKeyDatabaseShardingAlgorithm;
import org.tinygroup.dbcluster.base.ShardingValue;
import org.tinygroup.logger.Logger;
import org.tinygroup.logger.LoggerFactory;

import java.util.Collection;
import java.util.LinkedHashSet;

public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Integer> {
    private static final Logger logger = LoggerFactory.getLogger(ModuloDatabaseShardingAlgorithm.class);

    @Override
    public String doEqualSharding(final Collection<String> dataSourceNames, final ShardingValue<Integer> shardingValue) {
        for (String each : dataSourceNames) {
            Integer value = getIntValue(shardingValue.getValue());
            if (each.equalsIgnoreCase(getSchemaPre()+value % dataSourceNames.size() + "")) {
                logger.infoMessage("数据{0}被分配到{1}", value, each);
                return each;
            }
        }
        throw new IllegalArgumentException();
    }
    
    @Override
    public Collection<String> doInSharding(final Collection<String> dataSourceNames, final ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<String>(dataSourceNames.size());
        for (Object valObj : shardingValue.getValues()) {
            Integer value = getIntValue(valObj);
            for (String dataSourceName : dataSourceNames) {
                if (dataSourceName.equalsIgnoreCase(getSchemaPre()+value % dataSourceNames.size() + "")) {
                    result.add(dataSourceName);
                }
            }
        }
        return result;
    }
    
    @Override
    public Collection<String> doBetweenSharding(final Collection<String> dataSourceNames, final ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<String>(dataSourceNames.size());
        Range<Integer> range = shardingValue.getValueRange();
        for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            for (String each : dataSourceNames) {
                if (each.equalsIgnoreCase(getSchemaPre()+i % dataSourceNames.size() + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }

    private Integer getIntValue(Object shardingValObj) {
        Integer value;
        if(shardingValObj instanceof Long){
            value = ((Long) shardingValObj).intValue();
        }else if(shardingValObj instanceof Integer){
            value = (Integer) shardingValObj;
        }else{
            throw new UnsupportedOperationException("分片值非Integer或Long类型！");
        }
        return value;
    }

    protected String getSchemaPre(){
        return "biz_";
    }
}
